package com.g.ocache.impl.index;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.NavigableMap;
import java.util.TreeMap;

import com.g.ocache.enums.SortingOrder;
import com.g.ocache.index.Node;


/**
 * 
 * @author zhangyf
 * @param <K>
 * @param <V>
 */
public class BasicNode<K, V> extends AbstractNode<K, V> {
	//
	private final TreeMap<Object, Node<K, V>> children;
	
	/**
	 * 
	 */
	public BasicNode(Object id, Node<K, V> parent) {
		this(id, parent, null);
	}
	
	public BasicNode(Object id, Node<K, V> parent, Comparator<Object> comparator) {
		//
		super(id, parent);
		
		//
		if(comparator == null) {
			this.children = new TreeMap<Object, Node<K, V>>();
		} else {
			this.children = new TreeMap<Object, Node<K, V>>(comparator);
		}
	}
	
	/**
	 * 
	 */
	public void clear() {
		children.clear();
	}
	
	public void removeChild(Object id) {
		//
		children.remove(id);
		
		//
		if(children.size() == 0 && getParent() != null) {
			getParent().removeChild(getId());
		}
	}
	
	public void addChild(Object id, Node<K, V> child) {
		children.put(id, child);
	}
	
	public Node<K, V> getChild(Object id) {
		return children.get(id);
	}
	
	public List<Node<K, V>> getChildren() {
		return new LinkedList<Node<K, V>>(children.values());
	}
	
	public List<Node<K, V>> getChildren(Object from, boolean isFromInclusive, Object to, boolean isToInclusive, SortingOrder order) {
		//
		NavigableMap<Object, Node<K, V>> map = null;
		if (from != null && to != null) {
			map = children.subMap(from, isFromInclusive, to, isToInclusive);
		} else if (from != null) {
			map = children.tailMap(from, isFromInclusive);
		} else if (to != null) {
			map = children.headMap(to, isToInclusive);
		} else {
			map = children;
		}
		
		//
		List<Node<K, V>> r = null;
		switch (order) {
		case asc:
			r = new LinkedList<Node<K, V>>(map.values());
			break;
		case desc:
			r = new LinkedList<Node<K, V>>(map.descendingMap().values());
			break;
		}
		return r;
	}
}